
package com.hulk.ratel.web.exceptionhandler;


import com.google.common.base.Throwables;
import com.google.common.eventbus.EventBus;
import com.hulk.common.exception.BaseException;
import com.hulk.common.util.BeanMapper;
import com.hulk.common.util.JsonMapper;
import com.hulk.ratel.common.constant.enums.BussErrCode;

import com.hulk.ratel.common.exception.BaseRteException;
import com.hulk.ratel.service.dto.HeadReqDTO;
import com.hulk.ratel.service.dto.HeadRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;


/**
 * @author cmt
 */


@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    
    private final JsonMapper json = JsonMapper.JSON_NON_DEFAULT_MAPPER;


    @Autowired
    private EventBus eventBus;


    @ExceptionHandler(value = ClientAbortException.class)
    public void doErrorHandler(HttpServletRequest req, HttpServletResponse resp, ClientAbortException e) throws Exception {
        processException(req, resp, BussErrCode.E_900013.getErrCode(), BussErrCode.E_900013.getErrDesc(), e);
    }

    @ExceptionHandler(value = BaseException.class)
    //@ResponseBody
    public void doErrorHandler(HttpServletRequest req, HttpServletResponse resp, BaseException e) throws Exception {
//        recordError(e);
        processException(req, resp, e.getErrorCode(), e.getMessage(), e);
    }

    @ExceptionHandler(value = BaseRteException.class)
    public void doErrorHandler(HttpServletRequest req, HttpServletResponse resp, BaseRteException e) throws Exception {
        processException(req, resp, e.getErrorCode(), e.getMessage(), e);
    }

    @ExceptionHandler(value = Exception.class)
    public void doErrorHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) throws Exception {
        processException(req, resp, BussErrCode.E_999999.getErrCode(), BussErrCode.E_999999.getErrDesc(), e);
    }

    private void processException(HttpServletRequest req, HttpServletResponse resp, String errorCode, String errorMsg, Throwable e) throws Exception {

        String platformId = (String) req.getAttribute("platformId");
        String txnCode = (String) req.getAttribute("txnCode");
        String partnerNo = (String) req.getAttribute("partnerNo");
        String traceId = (String) req.getAttribute("traceId");
        log.error(" platformId:{}, traceId:{}, partnerNo:{}, txnCode:{},  errorCode:{},errorMsg:{},e:{}", new Object[]{
                platformId, traceId, partnerNo, txnCode, errorCode, errorMsg, Throwables.getStackTraceAsString(e)});
        String partnerAESKey = (String) req.getAttribute("partnerAESKey");
        String requestHead = (String) req.getAttribute("requestHead");
        HeadReqDTO reqHead = json.fromJson(requestHead, HeadReqDTO.class);
        HeadRespDTO respHead = new HeadRespDTO();
        BeanMapper.copyNotNull(reqHead, respHead);
        respHead.setTraceId(traceId);
        respHead.setPartnerNo(partnerNo);
        respHead.setTxnCode(txnCode);
        respHead.setPlatformId(platformId);
        DateTime now = DateTime.now();
        respHead.setRespDate(now.toString("yyyyMMdd"));
        respHead.setRespTime(now.toString("yyyyMMddHHmmss"));
        respHead.setRespCode(errorCode);
        respHead.setRespMsg(errorMsg);
        String respJson = "";
        PrintWriter wr = resp.getWriter();
        wr.write(respJson);
        wr.flush();
        wr.close();
        //return contentUtil.postHandle(respHead,partnerAESKey, partnerNo, platformId);
    }

    @ModelAttribute
    public void addAttribute(Model m) {
        log.debug("============应用到所有@RequestMapping注解方法，在其执行之前把返回值放入Model");
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        log.debug("============应用到所有@RequestMapping注解方法，在其执行之前初始化数据绑定器");
    }

}
